package heima_bixiangdong.test.review4;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @DESCRIPTION:    这个只是把 ManyProducerAndConsumerDemo 这个多生产多消费的例子用 JDK1.5之后的 锁机制进行了改写，并没有提升效率问题
 * @USER: shg
 * @DATE: 2022/11/26 17:40
 */
public class JDK5_ManyProducerAndConsumerDemo {
    public static void main(String[] args) {
        // 资源对象
        Resource_2 resource_2 = new Resource_2();

        // 生产任务
        Producer_2 producer_2 = new Producer_2(resource_2);
        // 消费任务
        Consumer_2 consumer_2 = new Consumer_2(resource_2);

        // 第一个生产线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                producer_2.produceBread();
            }
        }, "pro1").start();

        // 第二个生产线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                producer_2.produceBread();
            }
        }, "pro2").start();

        // 第一个消费线程
        new Thread(() -> consumer_2.eatBread(), "con1").start();

        // 第二个消费线程
        new Thread(consumer_2::eatBread, "con2").start();
    }
}

class Resource_2 {
    private String name;
    private int count = 1;
    private boolean flag = false;
    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();

    public void setName(String name) {
        // 获取锁
        lock.lock();
        try {
            while (flag) {
                try {
                    condition.await();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            this.name = name + count;
            count++;
            System.out.println(Thread.currentThread().getName() + "...生产者..." + this.name);
            flag = true;
            condition.signalAll();  // 此处的condition.signalAll()，并没有提升效率
        } finally {
            // 释放锁
            lock.unlock();
        }
    }

    public void out() {
        // 获取锁
        lock.lock();
        try {
            while (!flag) {
                try {
                    condition.await();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            // 如果标记为真，则说明盘子里有面包，消费者进行消费
            System.out.println(Thread.currentThread().getName() + "...消费者..." + this.name);
            // 消费完后，把标记改为假，并唤醒生产者进行生产
            flag = false;
            condition.signalAll();  // 此处的condition.signalAll()，并没有提升效率
        } finally {
            // 释放锁
            lock.unlock();
        }
    }
}

// 生产任务对象
@Data
@AllArgsConstructor
@NoArgsConstructor
class Producer_2 {

    private Resource_2 resource;

    public void produceBread() {
        while (true) {
            resource.setName("面包");
        }
    }
}

// 消费任务对象
@Data
@AllArgsConstructor
@NoArgsConstructor
class Consumer_2 {
    private Resource_2 resource;

    public void eatBread() {
        while (true) {
            resource.out();
        }
    }
}

